package club.itstudio.itouc.config

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.connection.RedisNode
import org.springframework.data.redis.connection.RedisPassword
import org.springframework.data.redis.connection.RedisSentinelConfiguration
import org.springframework.data.redis.connection.RedisStandaloneConfiguration
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory
import org.springframework.data.redis.core.*
import org.springframework.data.redis.serializer.StringRedisSerializer
import redis.clients.jedis.JedisPoolConfig

/**
 * redis配置
 */

@Configuration
class RedisConfig {
    // 是否单例连接，否的话使用集群连接
    private val standaloneConnect = true
    // 单例主机
    private val host = "localhost"
    // 单例端口
    private val port = 6379
    // 连接密码，单例和集群共用
    private val password = "HNT18UyVpIlOGVvC"
    // 集群连接配置
    val master = "mymaster"
    val nodes = "server1.itstudio.club:26379,server2.itstudio.club:26379,server3.itstudio.club:26379"

    // 连接池配置
    val maxIdle = 8
    val maxTotal = 16


    /**
     * 单机redis配置
     */
    @Bean
    fun standaloneRedisConfig(): RedisStandaloneConfiguration {
        val rsConfig = RedisStandaloneConfiguration(host, port)
        rsConfig.password = RedisPassword.of(password)
        return rsConfig
    }

    @Autowired
    lateinit var standaloneConfig: RedisStandaloneConfiguration

    /**
     * 连接池
     */
    @Bean
    fun jedisPoolConfig(): JedisPoolConfig {
        val jedisPoolConfig = JedisPoolConfig()
        jedisPoolConfig.maxIdle = maxIdle
        jedisPoolConfig.maxTotal = maxTotal
        return jedisPoolConfig
    }

    @Autowired
    lateinit var jedisPoolConfig: JedisPoolConfig

    /**
     * sentinel 集群配置
     */
    @Bean
    fun redisSentinelConfig(): RedisSentinelConfiguration {
        val config = RedisSentinelConfiguration()
        val hosts = nodes.split(",")
        hosts.forEach {host ->
            val item = host.split(":")
            val ip = item[0]
            val port = item[1]
            config.addSentinel(RedisNode(ip, port.toInt()))
        }
        config.setMaster(master)
        config.setPassword(password)
        return config
    }

    @Autowired
    lateinit var redisSentinelConfig: RedisSentinelConfiguration

    @Bean
    fun jedisConnectionFactory(): JedisConnectionFactory {
        return if(standaloneConnect)//单例连接
             JedisConnectionFactory(standaloneConfig)
        else // 集群连接
            JedisConnectionFactory(redisSentinelConfig, jedisPoolConfig)
    }

    @Autowired
    lateinit var jedisConnectionFactory: JedisConnectionFactory

    @Bean
    fun redisTemplate(): RedisTemplate<String, String> {
        val redisTemplate = RedisTemplate<String, String>()
        redisTemplate.setConnectionFactory(jedisConnectionFactory)
        val stringSerializer = StringRedisSerializer()
        redisTemplate.valueSerializer = stringSerializer
        redisTemplate.keySerializer = stringSerializer
        redisTemplate.hashKeySerializer = stringSerializer
        redisTemplate.hashValueSerializer = stringSerializer
        return redisTemplate
    }

    @Bean
    fun hashOps(redisTemplate: RedisTemplate<String, String>): HashOperations<String, String, String>{
        return redisTemplate().opsForHash()
    }

    @Bean
    fun valueOps(redisTemplate: RedisTemplate<String, String>): ValueOperations<String, String> {
        return redisTemplate.opsForValue()
    }

    @Bean
    fun listOps(redisTemplate: RedisTemplate<String, String>): ListOperations<String, String> {
        return redisTemplate.opsForList()
    }

    @Bean
    fun setOps(redisTemplate: RedisTemplate<String, String>): SetOperations<String, String> {
        return redisTemplate.opsForSet()
    }

    @Bean
    fun zsetOps(redisTemplate: RedisTemplate<String, String>): ZSetOperations<String, String> {
        return redisTemplate.opsForZSet()
    }
}